﻿/**************************************************************
 *
 * 唯一标识：fbecb5a1-78a2-44bb-9203-e4e6ee369dc4
 * 命名空间：Sgr.EntityFrameworkCore.EntityConfigurations
 * 创建时间：2023/8/6 10:09:08
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Sgr.EntityFrameworkCore.EntityConfigurations
{
    /// <summary>
    ///
    /// </summary>
    public static class EntityTypeBuilderExtension
    {
        /// <summary>
        /// 为值对象属性设置属性名称和列名称
        /// </summary>
        /// <typeparam name="TEntity">拥有者实体类型</typeparam>
        /// <typeparam name="TDependentEntity">值对象类型</typeparam>
        /// <typeparam name="TProperty">属性类型</typeparam>
        /// <param name="ownedNavigationBuilder">值对象导航构建器</param>
        /// <param name="propertyExpression">属性表达式</param>
        /// <param name="customName">自定义名称</param>
        /// <param name="columnNameCase">列名大小写设置</param>
        /// <param name="prefix">列名前缀</param>
        /// <returns>属性构建器</returns>
        public static PropertyBuilder<TProperty> PropertyAndHasColumnName<TEntity, TDependentEntity, TProperty>(
            this OwnedNavigationBuilder<TEntity, TDependentEntity> ownedNavigationBuilder,
            Expression<Func<TDependentEntity, TProperty>> propertyExpression,
            string customName = "",
            ColumnNameCase columnNameCase = ColumnNameCase.Lowercase,
            string prefix = "m")
            where TEntity : class
            where TDependentEntity : class
        {
            var propertyBuilder = ownedNavigationBuilder.Property(propertyExpression);

            if (string.IsNullOrWhiteSpace(customName))
            {
                var propertyName = propertyBuilder.Metadata.GetColumnName();
                customName = propertyName;
            }

            var columnName = GetColumnName(customName, prefix, columnNameCase);
            return propertyBuilder.HasColumnName(columnName);
        }

        public static PropertyBuilder PropertyAndHasColumnName(this EntityTypeBuilder builder,
            string propertyName,
            ColumnNameCase columnNameCase = ColumnNameCase.Lowercase,
            string prefix = "m")
        {
            var propertyBuilder = builder.Property(propertyName);

            return propertyBuilder.HasColumnName(GetColumnName(propertyName, prefix, columnNameCase));
        }

        public static PropertyBuilder<TProperty> PropertyAndHasColumnName<TProperty>(this EntityTypeBuilder builder,
            string propertyName,
            ColumnNameCase columnNameCase = ColumnNameCase.Lowercase,
            string prefix = "m")
        {
            var propertyBuilder = builder.Property<TProperty>(propertyName);

            return propertyBuilder.HasColumnName(GetColumnName(propertyName, prefix, columnNameCase));
        }

        public static PropertyBuilder<TProperty> PropertyAndHasColumnName<TEntity, TProperty>(this EntityTypeBuilder<TEntity> builder,
            Expression<Func<TEntity, TProperty>> propertyExpression,
            ColumnNameCase columnNameCase = ColumnNameCase.Lowercase,
            string prefix = "m") where TEntity : class
        {
            var propertyBuilder = builder.Property(propertyExpression);
            return propertyBuilder.HasColumnName(GetColumnName(propertyBuilder.Metadata.GetColumnName(), prefix, columnNameCase));
        }

        public static string GetColumnName(string propertyName, string prefix, ColumnNameCase columnNameCase)
        {
            string columnName = string.IsNullOrEmpty(prefix) ? propertyName : $"{prefix}_{propertyName}";
            switch (columnNameCase)
            {
                case ColumnNameCase.Lowercase:
                    columnName = columnName.ToLower();
                    break;

                case ColumnNameCase.Uppercase:
                    columnName = columnName.ToUpper();
                    break;

                case ColumnNameCase.Remaining:
                default:
                    break;
            }

            return columnName;
        }
    }
}